﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Timers;
using System.ComponentModel;
using System.Collections.ObjectModel;
using Xceed.Wpf.AvalonDock.Layout;

namespace BDSim
{
    //  [add by [Penghaijun] 2015.1.16
    /// <summary>
    /// EarthMapView.xaml 的交互逻辑
    /// </summary>
    public partial class EarthMapView : UserControl, INotifyPropertyChanged
    {
        #region 窗口构造函数
        public EarthMapView()
        {
            InitializeComponent();

            //世界地图上要显示的内容
            this.selectContentBox.ItemsSource = new List<DopEnum>()
            {
                DopEnum.Coverage,
                DopEnum.GDOP,
                DopEnum.PDOP,
                DopEnum.HDOP,
                DopEnum.VDOP,
                DopEnum.TDOP,                
                DopEnum.HNSP,
                DopEnum.VNSP,
                DopEnum.PNSP,
                DopEnum.TNSP,
            };
            selectContentBox.SelectedIndex = 0;

            //经纬度范围
            this.spaceBox.ItemsSource = new List<string>() { "2.5 * 5", "5 * 10", "7.5 * 15", "10 * 20" };
            spaceBox.SelectedIndex = 0;

            //是否考虑卫星数目
            //this.satNumBox.ItemsSource = new List<string>() { "GEO+IGSO+MEO", "IGSO+MEO", "MEO" };
            //satNumBox.SelectedIndex = 0;
        }
        #endregion

        #region 基本数据成员

        delegate void UpdataDisplayDelegate();
        /// <summary>
        /// 颜色种类 
        /// </summary>
        public int ColorNum { get { return colorRankView.ColorNum; } }
        //public int ColorNum { get { return 1; } }

        int rowNum = 72;
        /// <summary>
        /// 行数 
        /// </summary>
        public int RowNum { get { return rowNum; } }

        int colNum = 72;
        /// <summary>
        /// 列数 
        /// </summary>
        public int ColNum { get { return colNum; } }

        /// <summary>
        /// 选择显示的内容
        /// </summary>
        public DopEnum dopenum { get { return (DopEnum)selectContentBox.SelectedValue; } }

        /// <summary>
        /// 选择显示的卫星数目
        /// </summary>
        public int satNum;

        /// <summary>
        /// 卫星数
        /// </summary>
        ObservableCollection<Satellite> SatelliteList = new ObservableCollection<Satellite>();

        bool isSatLink = false;

        /// <summary>
        /// 是否考虑星间链路 
        /// </summary>
        public bool IsSatLink
        {
            get { return isSatLink; }
            set { isSatLink = value; }
        }

        bool _isWorking = false;
        //纬度值 
        double sliderValue_V1 = 0.0;
        public double SliderValue_V1
        {
            get
            {
                return Math.Abs(sliderValue_V1);
            }
        }

        /// <summary>
        /// 卫星号和其对应的图片，通过SatNameList来控制访问
        /// </summary>
        Dictionary<string, Image> SatImageList = new Dictionary<string, Image>();

        /// <summary>
        /// 卫星号和其对应的图片，通过SatNameList来控制访问
        /// </summary>
        Dictionary<Guid, Image> FacilitieImageList = new Dictionary<Guid, Image>();

        /// <summary>
        /// 用来保存场景中的卫星信息
        /// </summary>
        Dictionary<int, string> SatNameList = new Dictionary<int, string>();

        /// <summary>
        /// 二维显示线程
        /// </summary>
        System.Threading.Thread EarthMapThread;

        /// <summary>
        /// Dop评估是否可用
        /// </summary>
        bool EarthMapCanRun = true;


        Dictionary<Guid, DopAnalysisResult> EvaluationAreaDic = new Dictionary<Guid, DopAnalysisResult>();

        const int MaxX = 72;

        const int MaxY = 72;

        int rectangleCount = 0;

        int LineCount = 0;

        int EllipseCount = 0;

        int PointCount = 0;

        bool _IsDisplaySatDownTrack = false;

        public bool IsDisplaySatDownTrack
        {
            get { return _IsDisplaySatDownTrack; }
            set { _IsDisplaySatDownTrack = value; }
        }


        double _Lat;

        public double Lat
        {
            get { return Convert.ToDouble(_Lat.ToString("0.000000")); }
            set { _Lat = value; NotifyPropertyChanged("Lat"); }
        }

        double _Lon;

        public double Lon
        {
            get { return Convert.ToDouble(_Lon.ToString("0.000000")); }
            set { _Lon = value; NotifyPropertyChanged("Lon"); }
        }

        double _EleLim = 0;

        public double EleLim
        {
            get { return _EleLim; }
            set
            {
                if (value > 0 && value < 90)
                {
                    _EleLim = value;
                    NotifyPropertyChanged("EleLim");
                }
            }
        }

        #region//绘制评估区相关成员
        private SolidColorBrush color = new SolidColorBrush();
        private double thickness = 1;
        private double _opacity = 0.3;
        private Point startPosition;//开始按下点
        private Point endPosition;  //结束抬起点
        private Shape insertShape;  //图形形状
        private bool IsDrawPoint = false;
        private bool IsDrawArea = false;
        private bool _IsDrawTrack = true;


        public bool IsDrawTrack
        {
            get { return _IsDrawTrack; }
            set { _IsDrawTrack = value; NotifyPropertyChanged("IsDrawTrack"); }
        }

        public List<Line> TrackList = new List<Line>();
        private Shape shape;
        public double opacity
        {
            get { return _opacity; }
            set
            {
                if (value >= 0 && value <= 1)
                {
                    _opacity = value;
                }
                else
                {
                    MessageBox.Show("透明度需设置在[0,1]之间!");
                }
            }
        }
        #endregion

        #endregion

        #region//初始化可视化

        /// <summary>
        /// 初始化
        /// </summary>
        public void EarthMapInit()
        {
            RegisterEarthMapThread();
            this.myCanvas.Children.Clear();//初始化前，清除星下点轨迹和性能评估,kj
            if (IsDisplaySatDownTrack)
            {
                DisplaySatDownTrack();
            }
            PaintSats();
            UpdataDisplay();
            AddFacilitieToEarthMap();
            Start();
            EarthMapCanRun = true;
            //清除已有区域的评估结果
            ClearAreaEvaluationResult();

        }

        /// <summary>
        /// 初始化颜色条的范围，及注册可视化执行线程
        /// </summary>
        void RegisterEarthMapThread()
        {
            UpdateGridRowColumn(RowNum, ColNum);

            EarthMapThread = new System.Threading.Thread(new System.Threading.ThreadStart(ExctThread));
            EarthMapThread.IsBackground = true;
            EarthMapThread.Priority = System.Threading.ThreadPriority.Lowest;
            EarthMapThread.Name = "添加卫星轨道线程";
            //satNum = SimScenario.SatelliteList.Count;
            GetSatInfo();
            _isWorking = true;
        }

        /// <summary>
        /// 显示卫星星下点轨迹
        /// </summary>
        void DisplaySatDownTrack()
        {
            this.myCanvas.Children.Clear();
            List<SolidColorBrush> colorList = new List<SolidColorBrush>() { Brushes.Blue, Brushes.Red, Brushes.Green, Brushes.Yellow, Brushes.BlueViolet, Brushes.OrangeRed, Brushes.GreenYellow, Brushes.YellowGreen, Brushes.White, Brushes.Black };
            foreach (var item in SatelliteList)
            {
                if (item.IsShowSatTrack)
                {
                    List<BLH_PosVel> satBLHList = GetSatBLHList(item.OrbitPVList);
                    for (int i = 0; i < satBLHList.Count() - 1; i++)
                    {
                        double[] startPoint = GetPositionInCanvas(satBLHList[i].B, satBLHList[i].L);
                        double[] endPoint = GetPositionInCanvas(satBLHList[i + 1].B, satBLHList[i + 1].L);
                        Line line = new Line() { Stroke = colorList[item.Id % 10], StrokeThickness = 2 };
                        Canvas.SetLeft(line, startPoint[0]);
                        Canvas.SetTop(line, startPoint[1]);
                        line.X1 = 0;
                        line.X2 = endPoint[0] - startPoint[0];
                        line.Y1 = 0;
                        line.Y2 = endPoint[1] - startPoint[1];
                        if (Math.Abs(line.X2) < 100)
                        {
                            this.myCanvas.Children.Add(line);
                        }
                    }
                }
            }
        }

        List<BLH_PosVel> GetSatBLHList(List<OrbitSimData> satopv)
        {
            List<BLH_PosVel> blhList = new List<BLH_PosVel>();
            foreach (var item in satopv)
            {
                BLH_PosVel blh = new BLH_PosVel();
                NodePosVel satECF = new NodePosVel();
                TimeSpaceDll.ECI2ECF(item.SatPV_ECI, 0, 0, out satECF);
                TimeSpaceDll.XYZ2BLH(new NodePosVel() { x = satECF.X, y = satECF.Y, z = satECF.Z }, ECFtype.type_CGCS2000, out blh);
                //blhList.Add(new BLH_PosVel() { B = blh.B * 180 / Math.PI, L = blh.L * 180 / Math.PI, H = blh.H });
                blhList.Add(new BLH_PosVel() { B = blh.B, L = blh.L, H = blh.H });
            }

            return blhList;
        }

        double[] GetPositionInCanvas(double lat, double lon)
        {
            double[] xy = new double[2];
            double x = 0.0;//经度位置
            double y = 0.0;//纬度位置

            if (lon >= -30.0 && lon <= 180.0)
            {
                x = (1565.0 / 360.0) * (lon + 30.0);
            }
            if (lon >= -180.0 && lon < -30.0)
            {
                x = (1565.0 / 360.0) * (390.0 + lon);
            }

            y = (764.0 / 180.0) * (90.0 - lat);

            xy[0] = x;
            xy[1] = y;
            return xy;
        }


        /// <summary>
        /// 绘制网格   
        /// </summary>
        /// <param name="rowNum">网格行数</param>
        /// <param name="colNum">网格列数</param> 
        void UpdateGridRowColumn(int rowNum, int colNum)
        {
            planeMapView.Init(rowNum, colNum);
        }

        /// <summary>
        /// 通过仿真场景来控制线程的关和开
        /// </summary>
        void ExctThread()
        {
            while (_isWorking)
            {
                if (EarthMapThread.ThreadState == (System.Threading.ThreadState.Running | System.Threading.ThreadState.Background))
                {
                    try
                    {
                        EarthMapThread.Suspend();
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Trace.WriteLine(ex.Message);
                    }
                }
                this.Dispatcher.BeginInvoke(new UpdataDisplayDelegate(() => { UpdataDisplay(); }));
            }
        }

        /// <summary>
        /// 线程注册的执行事件，更新显示状态
        /// </summary>
        void UpdataDisplay()
        {
            Dop caldop = new Dop();
            caldop.RowNum = RowNum;
            caldop.ColNum = ColNum;
            caldop.ColorCount = ColorNum;
            //  首先得到经纬高度信息
            double[] satBLH = caldop.GetSatBLH(SatelliteList);
            //  更新地图上的卫星位置信息
            UpDateSatPos(satBLH);
            //FillColors(caldop.GetColor(OrbitList, earthMapView.dopenum),earthMapView.RowBegin);
            //  根据卫星的位置速度信息和误差信息，得到DOP，然后根据DOP设置地图显示的颜色
            if ((bool)PerformanceEvaluate.IsChecked)
            {
                double[,] evaluationData = new double[1, 1];
                int[,] values = caldop.GetColor(SatelliteList, EleLim, dopenum, satNum, IsSatLink, ref evaluationData);
                //heatMap1.FillColors(evaluationData);
                //  填充整个地图
                FillColors(values, (DopEnum)(selectContentBox.SelectedItem));

                CalDop(caldop.EvaluationValue);
            }
        }

        /// <summary>
        /// 往网格中填充颜色
        /// </summary>
        /// <param name="colorValue"></param>
        /// <param name="latBegin"></param>
        /// <param name="dopType"></param>
        void FillColors(int[,] colorValue, DopEnum dopType)
        {
            planeMapView.FillColors(colorValue, dopType);//填充全部网格
        }

        /// <summary>
        /// 获取覆盖区域的分析值
        /// </summary>
        /// <param name="values"></param>
        /// <param name="uid"></param>
        void CalDop(double[,] values)
        {
            List<double> evaluation = new List<double>();
            foreach (var item in EvaluationAreaDic)
            {
                evaluation.Clear();
                for (int i = 0; i < EvaluationAreaDic[item.Key].GridIndexList.Count; i++)
                {
                    int index_x = EvaluationAreaDic[item.Key].GridIndexList[i].RowIndex;
                    int index_y = EvaluationAreaDic[item.Key].GridIndexList[i].ColunmIndex;
                    evaluation.Add(values[index_x, index_y]);
                }
                EvaluationAreaDic[item.Key].AddData(evaluation, SatelliteList[0].CurTime);
            }
        }

        /// <summary>
        /// 更新所有卫星经纬度 
        /// </summary>
        /// <param name="satBLH">所有卫星的经纬高</param>
        void UpDateSatPos(double[] satBLH)
        {
            double lat = 0.0;
            double lon = 0.0;

            for (int i = 0, SatID = 0; i < satBLH.Count() && SatID < satNum; i += 3, SatID++)
            {
                lat = satBLH[i];
                lon = satBLH[i + 1];
                SatPos(SatNameList[SatID], lat, lon);
            }
        }

        /// <summary>
        /// 设置单个卫星的位置 
        /// </summary>
        /// <param name="satId">卫星ID</param>
        /// <param name="lat">纬度</param>
        /// <param name="lon">经度</param>
        void SatPos(string satName, double lat, double lon)
        {
            double x = 0.0;//经度位置
            double y = 0.0;//纬度位置
            double dx = 30.0;//卫星图片偏移位置
            double dy = 30.0;

            if (lat > 90.0 || lat < -90.0 || lon > 180.0 || lon < -180.0)
            {
                return;
            }

            if (lon >= -30.0 && lon <= 180.0)
            {
                x = (1565.0 / 360.0) * (lon + 30.0);
            }
            if (lon >= -180.0 && lon < -30.0)
            {
                x = (1565.0 / 360.0) * (390.0 + lon);
            }

            y = (764.0 / 180.0) * (90.0 - lat);

            Canvas.SetLeft(SatImageList[satName], x - dx / 2);//经度
            Canvas.SetTop(SatImageList[satName], y - dy / 2);//纬度            
        }

        /// <summary>
        /// 绘制卫星图标
        /// </summary>
        void PaintSats()
        {
            int IndexOfRemove = SatImageList.Count;//需要被移除的最后一个图片的下标
            for (int i = 0; i < IndexOfRemove; i++)
            {
                myCanvas.Children.Remove(SatImageList[SatNameList[i]]);
            }

            for (int i = 0; i < satNum; i++)
            {
                string satName = SatNameList[i];
                if (!myCanvas.Children.Contains(SatImageList[satName]))
                {
                    myCanvas.Children.Add(SatImageList[satName]);
                }
            }
        }

        /// <summary>
        /// 获取卫星数和卫星编号信息
        /// </summary>
        void GetSatInfo()
        {
            satNum = (((MainWindowViewModel)DataContext).Scenario.SegmentColletion[0] as SpaceSegment).AllSatellite.Count;
            SatelliteList = (((MainWindowViewModel)DataContext).Scenario.SegmentColletion[0] as SpaceSegment).AllSatellite;
            RemoveSats();
            SatImageList.Clear();
            //  清除卫星列表
            SatNameList = new Dictionary<int, string>();

            for (int i = 0; i < satNum; i++)
            {
                string satName = SatelliteList[i].Name;
                //int satID = SatelliteList[i].Id;
                SatNameList.Add(i, satName);

                Image tempImage = new Image();
                tempImage.ToolTip = SatelliteList[i].Name;

                ///判断卫星类型
                SatOrbit.enumSatType enumtempSatType = SatOrbit.GetSatType(SatelliteList[i].Orbit.RealECIPV);
                switch (enumtempSatType)
                {
                    case SatOrbit.enumSatType.MEO:
                        tempImage.Style = (Style)tempImage.FindResource("MEOSatImageStyle");
                        break;
                    case SatOrbit.enumSatType.GEO:
                        tempImage.Style = (Style)tempImage.FindResource("GEOSatImageStyle");
                        break;
                    case SatOrbit.enumSatType.IGSO:
                        tempImage.Style = (Style)tempImage.FindResource("IGSOSatImageStyle");
                        break;
                    case SatOrbit.enumSatType.LEO:
                        break;
                    case SatOrbit.enumSatType.HEO:
                        break;
                    default:
                        tempImage.Style = (Style)tempImage.FindResource("DefaultSatImageStyle");
                        break;
                }
                SatImageList.Add(satName, tempImage);
            }
        }

        /// <summary>
        /// 计算卫星轨道高度
        /// </summary>
        /// <param name="satECF"></param>
        /// <returns></returns>
        double CalculateOrbitAltitude(NodePosVel satECF)
        {
            double orbitAltitude = 0;
            double temp = 0;
            temp += satECF.x * satECF.x;
            temp += satECF.y * satECF.y;
            temp += satECF.z * satECF.z;
            orbitAltitude = Math.Sqrt(temp);
            return orbitAltitude;
        }

        /// <summary>
        /// 移除Canvas中所有卫星
        /// </summary>
        void RemoveSats()
        {
            int IndexOfRemove = SatImageList.Count;//需要被移除的最后一个图片的下标
            for (int i = 0; i < IndexOfRemove; i++)
            {
                string satName = SatNameList[i];
                myCanvas.Children.Remove(SatImageList[satName]);
            }
        }

        #endregion

        #region //加入地面站
        void AddFacilitieToEarthMap()
        {
            //foreach (var item in FacilitieImageList.Values)
            //{
            //    myCanvas.Children.Remove(item);
            //}
            //FacilitieImageList.Clear();
            //foreach (var item in SimScenario.MasterStationList)
            //{
            //    SetFacilitieInCanvas(item.modelType, item.NodeName,item.Uid, item.StaPosBLH.B, item.StaPosBLH.L);
            //}
            //foreach (var item in SimScenario.InjectionStationList)
            //{
            //    SetFacilitieInCanvas(item.modelType, item.NodeName, item.Uid, item.StaPosBLH.B, item.StaPosBLH.L);
            //}
            //foreach (var item in SimScenario.MonitorStationList)
            //{
            //    SetFacilitieInCanvas(item.modelType, item.NodeName, item.Uid, item.StaPosBLH.B, item.StaPosBLH.L);
            //}
        }

        /// <summary>
        /// 设置地面站的位置 
        /// </summary>
        /// <param name="lat">纬度</param>
        /// <param name="lon">经度</param>
        //void SetFacilitieInCanvas(ModelType facilitieType,string facilitieName,Guid uid, double lat, double lon)
        //{
        //    double x = 0.0;//经度位置
        //    double y = 0.0;//纬度位置
        //    double dx = 25.0;//卫星图片偏移位置
        //    double dy = 25.0;

        //    if (lat > 90.0 || lat < -90.0 || lon > 180.0 || lon < -180.0)
        //    {
        //        return;
        //    }

        //    if (lon >= -30.0 && lon <= 180.0)
        //    {
        //        x = (1694.0 / 360.0) * (lon + 30.0);
        //        //x = (847 / 360.0) * (lon + 30.0);
        //    }
        //    if (lon >= -180.0 && lon < -30.0)
        //    {
        //        x = (1695.0 / 360.0) * (390.0 + lon);
        //        //x = (847 / 360.0) * (390.0 + lon);
        //    }

        //    //y = (425 / 180.0) * (90.0 - lat);
        //    y = (764.0 / 180.0) * (90.0 - lat);
        //    Image facilitieImage = new Image();
        //    switch (facilitieType)
        //    {
        //        case ModelType.MasterStation:
        //            facilitieImage.Style = (Style)this.FindResource("MasterControlFacilitieImage");
        //            break;
        //        case ModelType.InjectionStation:
        //            facilitieImage.Style = (Style)this.FindResource("InjectionFacilitieImage");
        //            break;
        //        case ModelType.MonitorStation:
        //            facilitieImage.Style = (Style)this.FindResource("MonitorFacilitieImage");
        //            break;
        //        default:
        //            break;
        //    }
        //    facilitieImage.ToolTip = facilitieName;
        //    FacilitieImageList.Add(uid, facilitieImage);
        //    myCanvas.Children.Add(facilitieImage);
        //    Canvas.SetLeft(facilitieImage, x - dx/2);//经度
        //    Canvas.SetTop(facilitieImage, y - dy/2);//纬度
        //}
        #endregion

        #region 开始启动可视化

        void Start()
        {
            EarthMapThread.Start();
        }
        #endregion

        #region 暂停可视化更新

        void Pause()
        {
            if (_isWorking)
            {
                if (EarthMapThread.ThreadState == System.Threading.ThreadState.Background)
                {
                    try
                    {
                        EarthMapThread.Suspend();
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Trace.WriteLine(ex.Message);
                    }
                }
            }
        }
        #endregion

        #region 继续可视化更新
        void Resume()
        {
            if (_isWorking)
            {
                if (EarthMapThread.ThreadState == System.Threading.ThreadState.Suspended)
                {
                    try
                    {
                        EarthMapThread.Resume();
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Trace.WriteLine(ex.Message);
                    }
                }
            }
        }

        #endregion

        #region 结束可视化更新
        public void End()
        {
            if (_isWorking)
            {
                _isWorking = false;
                //  重置变量值
                SatelliteList = null;
                satNum = 0;

                //RemoveSats();
                try
                {
                    EarthMapThread.Abort();
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Trace.WriteLine(ex.Message);
                }
            }
        }

        #endregion

        #region //启动线程完成可视化执行，显示Dop分析结果

        /// <summary>
        /// 启动线程完成可视化执行，显示Dop分析结果
        /// </summary>
        public void Display()
        {
            if (_isWorking && EarthMapCanRun)
            {
                //GetSatInfo();
                SatelliteList = (((MainWindowViewModel)DataContext).Scenario.SegmentColletion[0] as SpaceSegment).AllSatellite;
                try
                {
                    if (EarthMapThread.ThreadState == (System.Threading.ThreadState.Suspended | System.Threading.ThreadState.Background))
                    {
                        EarthMapThread.Resume();
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Trace.WriteLine(ex.Message);
                }
            }
        }
        #endregion

        #region 经纬度间距改变，重新绘制网格(界面逻辑)

        /// <summary>
        /// 经纬度间距改变，重新绘制网格 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void spaceBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            string[] strSpace = GetRowAndCol();
            planeMapView.LatSpace = Convert.ToDouble(strSpace[0]);//纬度间距
            planeMapView.LonSpace = Convert.ToDouble(strSpace[1]);//经度间距
            this.rowNum = (int)(180.0 / Convert.ToDouble(strSpace[0]));//行数
            this.colNum = (int)(360.0 / Convert.ToDouble(strSpace[1]));//列数
            //重新绘制网格
            planeMapView.Init(RowNum, ColNum);
        }

        /// <summary>
        /// 通过经纬度间距，获得行数和列数 
        /// </summary>
        /// <returns></returns>
        string[] GetRowAndCol()
        {
            string str = spaceBox.SelectedValue.ToString();
            string[] delStr = { "*" };
            string[] strSpace = str.Split(delStr, StringSplitOptions.RemoveEmptyEntries);
            return strSpace;
        }

        #endregion

        #region 改变评估指标类型执行事件（界面逻辑）
        private void selectContentBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            UpdateLimits();
            ClearAreaEvaluationResult();
        }

        /// <summary>
        /// 更新评估性能取值的范围
        /// </summary>
        private void UpdateLimits()
        {
            //  调整DOP的取值范围,
            double[] limits = GetLimits(dopenum, IsSatLink);
            //  根据输入的DOP大小调整图例的范围
            SetFigure(limits[0], limits[1]);
        }

        /// <summary>
        /// 获取取值范围 
        /// </summary>
        /// <param name="cde">参数类型</param>
        /// <param name="IsLinkConsidered">是否考虑星间链路</param>
        /// <returns>取值范围最大值和最小值</returns>
        public double[] GetLimits(DopEnum cde, bool IsLinkConsidered)
        {
            double[] limits = new double[2];
            switch (cde)
            {
                case DopEnum.Coverage:
                    limits[0] = 3;
                    limits[1] = 15;
                    break;
                case DopEnum.GDOP:
                    limits[0] = 1;
                    limits[1] = 5;
                    break;
                case DopEnum.HDOP:
                    limits[0] = 0.8;
                    limits[1] = 3;
                    break;
                case DopEnum.PDOP:
                    limits[0] = 1.3;
                    limits[1] = 4;
                    break;
                case DopEnum.TDOP:
                    limits[0] = 0.6;
                    limits[1] = 2;
                    break;
                case DopEnum.VDOP:
                    limits[0] = 0.5;
                    limits[1] = 3;
                    break;
                case DopEnum.HNSP:
                    if (IsLinkConsidered)
                    {
                        limits[0] = 0.475;
                        limits[1] = 2.5;
                    }
                    else
                    {
                        limits[0] = 1.55;
                        limits[1] = 6;
                    }
                    break;
                case DopEnum.PNSP:
                    if (IsLinkConsidered)
                    {
                        limits[0] = 0.8;
                        limits[1] = 2.5;
                    }
                    else
                    {
                        limits[0] = 2.5;
                        limits[1] = 6.5;
                    }
                    break;
                case DopEnum.TNSP:
                    if (IsLinkConsidered)
                    {
                        limits[0] = 0.4;
                        limits[1] = 1.6;
                    }
                    else
                    {
                        limits[0] = 1.2;
                        limits[1] = 5;
                    }
                    break;
                case DopEnum.VNSP:
                    if (IsLinkConsidered)
                    {
                        limits[0] = 0.3;
                        limits[1] = 2;
                    }
                    else
                    {
                        limits[0] = 1;
                        limits[1] = 6;
                    }
                    break;
            }
            return limits;
        }

        /// <summary>
        /// 设置图例对应的数值
        /// </summary>
        /// <param name="min">最小值</param>
        /// <param name="max">最大值</param>
        void SetFigure(double min, double max)
        {
            colorRankView.SetFigure(min, max, (DopEnum)(selectContentBox.SelectedItem));
        }

        /// <summary>
        /// 清除已有区域的评估结果
        /// </summary>
        private void ClearAreaEvaluationResult()
        {
            foreach (var item in EvaluationAreaDic)
            {
                item.Value.ClearAllData();
            }
        }
        #endregion

        #region //绘制评估区域

        private void ColorButton_Click(object sender, RoutedEventArgs e)
        {
            color = (SolidColorBrush)((Border)(sender as RadioButton).Content).Background;
        }

        private void ThicknessButton_Click(object sender, RoutedEventArgs e)
        {
            thickness = ((Ellipse)(sender as RadioButton).Content).Width;
        }

        private void ShapeButton_Click(object sender, RoutedEventArgs e)
        {
            if ((sender as RadioButton).Content is Shape)
            {
                shape = (Shape)(sender as RadioButton).Content;//绘制区域
                IsDrawPoint = false;
            }
            else if ((sender as RadioButton).Content is Image)
            {
                IsDrawPoint = true;//绘制单点
            }
        }

        private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (cbxCustomEvaluation.IsChecked == false)
            {
                IsDrawTrack = false;
            }

            if (cbxCustomEvaluation.IsChecked == true)
            {
                insertShape = CreateShape();
                if (!IsDrawPoint && insertShape != null)
                {
                    IsDrawArea = true;
                    Canvas board = sender as Canvas;
                    startPosition = e.GetPosition(board);

                    insertShape.Opacity = opacity / 2;
                    Canvas.SetLeft(insertShape, e.GetPosition(board).X);
                    Canvas.SetTop(insertShape, e.GetPosition(board).Y);
                    board.Children.Add(insertShape);
                }
                else if (IsDrawPoint)
                {
                    EnterNameWnd enterNameWnd = new EnterNameWnd();
                    Canvas board = sender as Canvas;
                    startPosition = e.GetPosition(board);
                    enterNameWnd.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                    if (enterNameWnd.ShowDialog() == true)
                    {
                        DopAnalysisResult result = new DopAnalysisResult();

                        Image tempImage = new Image();
                        tempImage.Style = (Style)this.FindResource("PointImage");
                        tempImage.ContextMenu = (ContextMenu)this.FindResource("FunctionMenu");
                        tempImage.ToolTip = enterNameWnd.EnterName;
                        result.Name = enterNameWnd.EnterName;
                        PointCount++;

                        ///获取点所在网格行列
                        int rowIndex = (int)((startPosition.X / board.Width) * MaxX);
                        int columnIndex = (int)((startPosition.Y / board.Height) * MaxY);
                        result.GridIndexList = new List<GridIndex>() { new GridIndex() { RowIndex = rowIndex, ColunmIndex = columnIndex } };

                        Guid tempUID = Guid.NewGuid();
                        tempImage.Tag = tempUID;
                        result.Uid = tempUID;
                        EvaluationAreaDic.Add(tempUID, result);

                        Canvas.SetLeft(tempImage, startPosition.X - tempImage.Width);
                        Canvas.SetTop(tempImage, startPosition.Y - tempImage.Height);
                        board.Children.Add(tempImage);
                    }
                }
            }

        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            Canvas board = sender as Canvas;
            Lat = -(e.GetPosition(board).Y - board.Height / 2) / (board.Height / 2) * 90;
            Lon = ((e.GetPosition(board).X - board.Width / 12) % (board.Width / 2)) / (board.Width / 2) * 180;
            if ((e.GetPosition(board).X - board.Width / 12) / (board.Width / 2) > 1)
            {
                Lon = Lon - 180.0;
            }

            if (IsDrawArea && insertShape != null && !IsDrawPoint)
            {
                if (insertShape is Line)
                {
                    (insertShape as Line).X1 = 0; (insertShape as Line).X2 = e.GetPosition(board).X - startPosition.X;
                    (insertShape as Line).Y1 = 0; (insertShape as Line).Y2 = e.GetPosition(board).Y - startPosition.Y;
                }
                else
                {
                    if (e.GetPosition(board).X > startPosition.X)
                    {
                        insertShape.Width = e.GetPosition(board).X - startPosition.X;
                    }
                    else
                    {
                        insertShape.Width = startPosition.X - e.GetPosition(board).X;
                        Canvas.SetLeft(insertShape, e.GetPosition(board).X);
                    }
                    if (e.GetPosition(board).Y > startPosition.Y)
                    {
                        insertShape.Height = e.GetPosition(board).Y - startPosition.Y;
                    }
                    else
                    {
                        insertShape.Height = startPosition.Y - e.GetPosition(board).Y;
                        Canvas.SetTop(insertShape, e.GetPosition(board).Y);
                    }
                }
            }

            if (!IsDrawTrack && TrackList.Count != 0)
            {
                if (TrackList.Last() is Line)
                {
                    (TrackList.Last() as Line).X1 = 0; (TrackList.Last() as Line).X2 = e.GetPosition(board).X - startPosition.X;
                    (TrackList.Last() as Line).Y1 = 0; (TrackList.Last() as Line).Y2 = e.GetPosition(board).Y - startPosition.Y;
                }
            }
        }

        private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (insertShape != null && IsDrawArea && !IsDrawPoint)
            {
                EnterNameWnd enterNameWnd = new EnterNameWnd();
                Canvas board = sender as Canvas;
                endPosition = e.GetPosition(board);
                enterNameWnd.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                if (enterNameWnd.ShowDialog() == true)
                {
                    insertShape.Opacity = opacity;
                    insertShape.ToolTip = enterNameWnd.EnterName;
                    insertShape.ContextMenu = (ContextMenu)this.FindResource("FunctionMenu");
                    insertShape.Style = (Style)this.FindResource("mouseOverTrigger");

                    //索引计算
                    DopAnalysisResult result = new DopAnalysisResult();
                    Point top = new Point();
                    Point bottom = new Point();
                    top.X = (startPosition.X / board.Width) * MaxX;
                    top.Y = (startPosition.Y / board.Height) * MaxY;
                    bottom.X = (endPosition.X / board.Width) * MaxX;
                    bottom.Y = (endPosition.Y / board.Height) * MaxY;
                    if (insertShape is Line)
                    {
                        result.GridIndexList = CoverIndex.CalCoverIndex(top, bottom, 0);
                    }
                    else if (insertShape is Rectangle)
                    {
                        result.GridIndexList = CoverIndex.CalCoverIndex(top, bottom, 1);
                    }
                    else if (insertShape is Ellipse)
                    {
                        result.GridIndexList = CoverIndex.CalCoverIndex(top, bottom, 2);
                    }
                    Guid tempUID = Guid.NewGuid();
                    insertShape.Tag = tempUID;
                    result.Uid = tempUID;
                    result.Name = enterNameWnd.EnterName;
                    EvaluationAreaDic.Add(tempUID, result);
                }
                else
                {
                    board.Children.Remove(insertShape);
                }
                IsDrawArea = false;
            }

            if (!IsDrawTrack)
            {
                Canvas board = sender as Canvas;
                startPosition = e.GetPosition(board);
                Line newTrack = new Line() { Stroke = Brushes.Red, StrokeThickness = 3, Style = (Style)this.FindResource("mouseOverTrigger"), ToolTip = "line" + LineCount };
                Canvas.SetLeft(newTrack, e.GetPosition(board).X);
                Canvas.SetTop(newTrack, e.GetPosition(board).Y);
                TrackList.Add(newTrack);
                board.Children.Add(newTrack);
            }
        }

        private void Canvas_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (!IsDrawTrack)
            {
                Canvas board = sender as Canvas;
                IsDrawTrack = true;
                board.Children.Remove(TrackList.Last());
                TrackList.Remove(TrackList.Last());
            }
        }

        private Shape CreateShape()
        {
            if (shape is Rectangle)
            {
                rectangleCount++;
                return new Rectangle() { Fill = color, Stroke = Brushes.Black, StrokeThickness = thickness, Style = (Style)this.FindResource("mouseOverTrigger"), ToolTip = "rectangle" + rectangleCount };
            }
            else if (shape is Ellipse)
            {
                EllipseCount++;
                return new Ellipse() { Fill = color, Stroke = Brushes.Black, StrokeThickness = thickness, Style = (Style)this.FindResource("mouseOverTrigger"), ToolTip = "ellipse" + EllipseCount };
            }
            else
            {
                return null;
            }
        }

        private void ContextMenu_Click(object sender, RoutedEventArgs e)
        {
            ContextMenu cm = sender as ContextMenu;
            FrameworkElement selectArea = (FrameworkElement)cm.PlacementTarget;
            switch ((e.OriginalSource as MenuItem).Header.ToString())
            {
                case "删除":
                    DeleteEvaluateArea(selectArea);
                    break;
                case "评估当前目标":
                    DopEvaluation((Guid)selectArea.Tag, selectArea.ToolTip.ToString());
                    break;
                case "评估所有目标":
                    AllDopEvaluation();
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 删除评估区域，并同时删除数据分析
        /// </summary>
        void DeleteEvaluateArea(FrameworkElement area)
        {
            EvaluationAreaDic.Remove((Guid)area.Tag);
            (area.Parent as Canvas).Children.Remove(area);
        }

        /// <summary>
        /// 评估当前目标
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="name"></param>
        void DopEvaluation(Guid uid, string name)
        {
            DopEvaluationView dev = new DopEvaluationView();
            dev.EvaluationType = (DopEnum)this.selectContentBox.SelectedItem;
            dev.InitCharts();
            if (EvaluationAreaDic.Keys.Contains(uid))
            {
                dev.DisplayDopEvaluation(EvaluationAreaDic[uid]);
                MainDispatcher.DlgAddLayoutDocument(dev, name + "_性能分析");
            }
        }

        void AllDopEvaluation()
        {
            AllDopEvaluationView allDop = new AllDopEvaluationView();
            allDop.InitCharts((DopEnum)selectContentBox.SelectedItem);
            allDop.DisplayDopEvaluation(EvaluationAreaDic);
            MainDispatcher.DlgAddLayoutDocument(allDop, "整体评估");
        }
        #endregion

        #region NotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion

        #region //确定地图纵横比
        private void gridEarthmap_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            //确定地图横：纵 = 1.6：1
            double scale = 1.8;
            Size newSize = e.NewSize;
            if (newSize.Height * scale <= newSize.Width)
            {
                gridEarthmap.Width = newSize.Height * scale;
                gridEarthmap.Height = newSize.Height;

                //heatMap1.chartViewer1.Width = Convert.ToInt32( newSize.Height * scale);
                //heatMap1.chartViewer1.Height = Convert.ToInt32(newSize.Height);
                //if (heatMap1.chartViewer1.Chart!=null)
                //{
                //    (heatMap1.chartViewer1.Chart as ChartDirector.XYChart).setPlotArea(0, 0, Convert.ToInt32(newSize.Height * scale), Convert.ToInt32(newSize.Height), -1, -1, -1, (new ChartDirector.XYChart(20, 20)).dashLineColor(unchecked((int)0x80000000),
                //ChartDirector.Chart.DotLine), -1);
                //}

            }
            else if (newSize.Height * scale >= newSize.Width)
            {
                gridEarthmap.Width = newSize.Width;
                gridEarthmap.Height = newSize.Width / scale;

                //heatMap1.chartViewer1.Width = Convert.ToInt32(newSize.Width);
                //heatMap1.chartViewer1.Height = Convert.ToInt32( newSize.Width / scale);

                //if (heatMap1.chartViewer1.Chart != null)
                //{
                //    (heatMap1.chartViewer1.Chart as ChartDirector.XYChart).setPlotArea(0, 0, Convert.ToInt32(newSize.Width), Convert.ToInt32(newSize.Width / scale), -1, -1, -1, (new ChartDirector.XYChart(20, 20)).dashLineColor(unchecked((int)0x80000000),
                //ChartDirector.Chart.DotLine), -1);
                //}
            }
        }
        #endregion
    }

    public class CoverIndex
    {
        //type=0:直线，type=1:矩形,type=2:椭圆
        public static List<GridIndex> CalCoverIndex(Point top, Point bottom, int type)
        {
            //GridIndex[] cover=new GridIndex[0];
            List<GridIndex> coverArray = new List<GridIndex>();
            switch (type)
            {
                case 0:
                    coverArray = CalLine(top, bottom);
                    break;
                case 1:
                    coverArray = CalRectangle(top, bottom);
                    break;
                case 2:
                    coverArray = CalEllipse(top, bottom);
                    break;
                default:
                    break;
            }
            return coverArray;
        }

        private static List<GridIndex> CalRectangle(Point top, Point bottom)
        {
            //GridIndex[] cover = new GridIndex[0];
            List<GridIndex> coverArray = new List<GridIndex>();
            if (top.X > bottom.X)
            {
                Point pp = top;
                top = bottom;
                bottom = pp;
            }
            else
            {
                int top_x = (int)Math.Floor(top.X);
                int top_y = (int)Math.Floor(top.Y);
                int bottom_x = (int)Math.Ceiling(bottom.X);
                int bottom_y = (int)Math.Ceiling(bottom.Y);
                int Num = (bottom_y - top_y) * (bottom_x - top_x);
                for (int i = top_x; i < bottom_x; i++)
                {
                    for (int j = top_y; j < bottom_y; j++)
                    {
                        GridIndex temp = new GridIndex();
                        temp.RowIndex = i;
                        temp.ColunmIndex = j;
                        coverArray.Add(temp);
                    }
                }
            }
            return coverArray;
        }

        private static List<GridIndex> CalLine(Point top, Point bottom)
        {
            List<GridIndex> coverArray = new List<GridIndex>();
            int Num = 0;
            if (top.X - bottom.X > 0)//需保证top的x值比bottom的x值小,是以x增大的方向搜索的
            {
                Point pp = top;
                top = bottom;
                bottom = top;
            }
            else
            {
                int top_x, top_y, bottom_x, bottom_y;
                int index = 0;
                //先判断有无特殊情况水平线和垂直线
                if (Math.Abs(top.X - bottom.X) < Math.Pow(10.0, -12.0))//垂直线
                {
                    int up, down;
                    if (top.Y < bottom.Y)
                    {
                        up = (int)Math.Floor(top.Y);
                        down = (int)Math.Floor(bottom.Y);
                        Num = down - up + 1;
                    }
                    else
                    {
                        up = (int)Math.Floor(bottom.Y);
                        down = (int)Math.Floor(top.Y);
                        Num = down - up + 1;
                    }
                    for (int i = 0; i < Num; i++)
                    {
                        GridIndex temp = new GridIndex();
                        temp.RowIndex = (int)Math.Floor(top.X);
                        temp.ColunmIndex = up + i;
                        coverArray.Add(temp);
                    }
                }
                else if (Math.Abs(top.Y - bottom.Y) < Math.Pow(10.0, -12.0))//水平线
                {
                    //x大小已定
                    int left = (int)Math.Floor(top.X);
                    int right = (int)Math.Floor(bottom.X);
                    Num = right - left + 1;
                    for (int i = 0; i < Num; i++)
                    {
                        GridIndex temp = new GridIndex();
                        temp.RowIndex = left + i;
                        temp.ColunmIndex = (int)Math.Floor(top.Y);
                        coverArray.Add(temp);
                    }
                }
                else//斜线
                {
                    //求直线方程y=ax+b
                    double a = (top.Y - bottom.Y) / (top.X - bottom.X);
                    double b = top.Y - a * top.X;
                    double Y = 0;
                    if (a < 0)
                    {
                        top_x = (int)Math.Floor(top.X);
                        top_y = (int)Math.Ceiling(top.Y);
                        bottom_x = (int)Math.Ceiling(bottom.X);
                        bottom_y = (int)Math.Floor(bottom.Y);
                        int kk = bottom_x - top_x;

                        int[] left_y = new int[kk + 1];
                        int[] right_y = new int[kk + 1];

                        left_y[0] = top_y;
                        right_y[0] = 0;
                        left_y[kk] = 0;
                        right_y[kk] = bottom_y;
                        index = 1;
                        for (int i = top_x + 1; i < bottom_x; i++)
                        {
                            Y = a * i + b;
                            left_y[index] = (int)Math.Ceiling(Y);
                            right_y[index] = (int)Math.Floor(Y);
                            index++;
                        }
                        /*cout << "left_y" << endl;
                        for (int i = 0; i < kk + 1; i++)
                        {
                        cout << left_y[i] << " ";
                        }
                        cout << endl;
                        cout << "right_y" << endl;
                        for (int i = 0; i < kk + 1; i++)
                        {
                        cout << right_y[i] << " ";
                        }
                        cout << endl;*/
                        for (int i = 0; i < kk; i++)
                        {
                            for (int j = right_y[i + 1]; j < left_y[i]; j++)
                            {
                                GridIndex temp;
                                temp.RowIndex = top_x + i;
                                temp.ColunmIndex = j;
                                coverArray.Add(temp);
                            }
                        }
                    }
                    else if (a > 0)
                    {
                        top_x = (int)Math.Floor(top.X);
                        top_y = (int)Math.Floor(top.Y);
                        bottom_x = (int)Math.Ceiling(bottom.X);
                        bottom_y = (int)Math.Ceiling(bottom.Y);
                        int kk = bottom_x - top_x;

                        int[] left_y = new int[kk + 1];
                        int[] right_y = new int[kk + 1];

                        left_y[0] = top_y;
                        right_y[0] = 0;
                        left_y[kk] = 0;
                        right_y[kk] = bottom_y;
                        index = 1;
                        for (int i = top_x + 1; i < bottom_x; i++)
                        {
                            Y = a * i + b;
                            left_y[index] = (int)Math.Floor(Y);
                            right_y[index] = (int)Math.Ceiling(Y);
                            index++;
                        }
                        for (int i = 0; i < kk; i++)
                        {
                            for (int j = left_y[i]; j < right_y[i + 1]; j++)
                            {
                                GridIndex temp;
                                temp.RowIndex = top_x + i;
                                temp.ColunmIndex = j;
                                coverArray.Add(temp);
                            }
                        }

                    }

                }
            }

            return coverArray;
        }

        private static List<GridIndex> CalEllipse(Point top, Point bottom)
        {
            //GridIndex[] cover = new GridIndex[0];
            List<GridIndex> coverArray = new List<GridIndex>();
            if (top.X > bottom.X)
            {
                Point pp = top;
                top = bottom;
                bottom = pp;
            }
            else
            {
                //构建椭圆方程，注：椭圆在坐标系中长短半轴是与坐标轴平行的
                Point O = new Point();
                O.X = (top.X + bottom.X) / 2;
                O.Y = (top.Y + bottom.Y) / 2;
                double a = (bottom.X - top.X) / 2;
                double b = Math.Abs(bottom.Y - top.Y) / 2;
                int top_x = (int)Math.Floor(top.X);
                int top_y = (int)Math.Floor(top.Y);
                int bottom_x = (int)Math.Ceiling(bottom.X);
                int bottom_y = (int)Math.Ceiling(bottom.Y);
                double Y1 = 0;
                double Y2 = 0;
                int up = 0;
                int down = 0;
                for (int i = top_x + 1; i < bottom_x; i++)
                {
                    Y1 = O.Y - Math.Sqrt(a * a - (i - O.X) * (i - O.X)) * b / a;
                    Y2 = O.Y + Math.Sqrt(a * a - (i - O.X) * (i - O.X)) * b / a;
                    up = (int)Math.Floor(Y1);
                    down = (int)Math.Ceiling(Y2);
                    for (int j = up; j < down; j++)
                    {
                        GridIndex temp;
                        temp.RowIndex = i - 1;
                        temp.ColunmIndex = j;
                        coverArray.Add(temp);
                    }
                }
            }
            return coverArray;
        }
    }
}
